import { CodeBlock, Line, Node, parse, Table, } from "../scrapbox-parser/mod.ts"; export const convert = (text: string): string => { const blocks = parse(text, { hasTitle: false }); return blocks.flatMap((block) => { switch (block.type) { case "title": return []; case "codeBlock": return convertCodeBlock(block); case "table": return convertTable(block); case "line": return convertLine(block); } }) .map((line) => line).join("\n"); }; /** コードブロックはそのまま復元する */ const convertCodeBlock = ( { fileName, content, indent }: CodeBlock, ) => { const tag = " ".repeat(indent); return [ `${tag}code:${fileName}`, ...content.split("\n").map((line) => `${tag} ${line}`), ]; }; /** テーブル中のリンクを外す */ const convertTable = ({ fileName, cells, indent }: Table) => { const tag = " ".repeat(indent); return [ `${tag}table:${fileName}`, ...cells.map((cell) => `${tag} ${ cell.map((nodes) => nodes.map((node) => convertNode(node)).join("")).join("\t") }` ), ]; }; /** 行内リンクを外す */ const convertLine = ({ nodes, indent }: Line) => [ `${" ".repeat(indent)}${ nodes.map((node) => `${convertNode(node)}`).join( "", ) }`, ]; /** リンクを外したnodeを作る */ const convertNode = (node: Node): string => { switch (node.type) { case "quote": return `> ${node.nodes.map((node) => convertNode(node)).join("")}`; case "strong": return `[[${node.nodes.map((node) => convertNode(node)).join("")}]]`; case "decoration": { const deco = node.decos.map((deco) => { const num = parseInt(deco.match(/\*-(\d)/)?.[1] ?? "0"); return num > 0 ? "*".repeat(num) : deco; }).join(""); return `[${deco ? `${deco} ` : ""}${ node.nodes.map((node) => convertNode(node)).join("") }]`; } case "hashTag": return node.href; // linterのバグで、何故か警告が出る // deno-lint-ignore no-fallthrough case "link": return node.pathType === "absolute" ? node.raw : node.href; default: return node.raw; } };